/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.community.manager;

import cn.ac.nercis.pes.community.component.controls.PesComboBox;
import cn.ac.nercis.pes.community.component.spreadsheet.TableSheetView;
import cn.ac.nercis.pes.community.support.event.CommonCallback;
import cn.hutool.core.convert.Convert;
import javafx.scene.control.CheckBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TextInputControl;
import javafx.scene.control.ToggleGroup;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 实时保存事件管理
 * @author zpy
 * @version 1.0.0
 */
@Slf4j
public final class RealTimeSaveManager {
    private final CommonCallback callback;

    private Boolean enable = true;

    public RealTimeSaveManager(CommonCallback commonCallback){
        this.callback = commonCallback;
    }

    public Boolean getEnable(){
        return this.enable;
    }

    public void setEnable(Boolean enable){
        this.enable = enable;
    }

    public void listenerTextChange(TextInputControl... controls){
        Arrays.stream(controls).forEach(node->{
            node.textProperty().addListener((observableValue, oldValue, newValue) -> {
                if(Objects.nonNull(oldValue)){
                    node.setUserData(!StringUtils.equals(oldValue,newValue));
                }
            });
            node.focusedProperty().addListener((observableValue, oldValue, newValue) -> {
                if(!newValue){
                    if(enable && Convert.toBool(node.getUserData(),false)){
                        callback.action();
                        node.setUserData(false);
                    }
                }
            });
        });
    }

    public void listenerDateChange(DatePicker... controls){
        Arrays.stream(controls).forEach(node->{
            node.valueProperty().addListener((observableValue, oldValue, newValue) -> {
                if(Objects.nonNull(oldValue)){
                    node.setUserData(!oldValue.isEqual(newValue));
                }
            });
            node.focusedProperty().addListener((observableValue, oldValue, newValue) -> {
                if(!newValue){
                    if(enable && Convert.toBool(node.getUserData(),false)){
                        callback.action();
                        node.setUserData(false);
                    }
                }
            });
        });
    }

    public void listenerComboBoxChange(PesComboBox... controls){
        Arrays.stream(controls).forEach(node->{
            node.valueProperty().addListener((observableValue, oldValue, newValue) -> {
                if(StringUtils.isNotEmpty(oldValue)){
                    node.setUserData(!StringUtils.equals(oldValue,newValue));
                }
            });
            node.contentFocusedProperty().addListener((observableValue, oldValue, newValue) -> {
                if(!newValue){
                    if(enable && Convert.toBool(node.getUserData(),false)){
                        callback.action();
                        node.setUserData(false);
                    }
                }
            });
        });
    }

    public void listenerCheckboxChange(List<CheckBox> controls){
        controls.forEach(node->{
            node.selectedProperty().addListener((observableValue, oldValue, newValue) -> {
                if(enable){
                    callback.action();
                }
            });
        });
    }

    @SafeVarargs
    public final <T extends TableSheetView<?>> void listenerSheetChange(T... controls){
        Arrays.stream(controls).forEach(node-> node.changeProperty().addListener((observableValue, oldValue, newValue) -> {
            if(enable && newValue){
                callback.action();
                node.resetChange();
            }
        }));
    }

    public void listenerToggleGroupChange(ToggleGroup... controls){
        Arrays.stream(controls).forEach(node-> node.selectedToggleProperty().addListener((observableValue, oldValue, newValue) -> {
            if(enable && Objects.nonNull(oldValue)){
                callback.action();
            }
        }));
    }

    public void onChange(){
        if(enable && Objects.nonNull(callback)){
            callback.action();
        }
    }
}